// 2021.03.05

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX_FILE_LENGTH     5000
#define MAX_WORD_LENGTH     64
#define MAX_WORD_NUM        256
#define MAX_INT_NUM         256

// read contents from a file pointer to a char array;
// return how many chars are read
int read_file_to_(char file[], FILE* fp) {
    int i = 0;
    int ch;
    while ((ch = getc(fp)) != EOF) {
        if (ch == '\n' || ch == '\r') ch = ' ';
        file[i] = ch;
        ++i;
        if (i == MAX_FILE_LENGTH) break;
    }
    file[i] = '\0'; // null character
    return i; // return how many chars are read
}

// returns 1 for letter, 0 for not letter and didn't count,
// return value may not be used
int add_letter_freq(char ch, int letter_cnt[]) {
    if (ch >= 'a' && ch <= 'z') { letter_cnt[1  + (ch - 'a')] += 1; return 1; }
    if (ch >= 'A' && ch <= 'Z') { letter_cnt[27 + (ch - 'A')] += 1; return 1; }
    return 0;
}

// 返回最长单词的数目
int find_max_len_word_in_(char file[], int length, char max_len_words[][MAX_WORD_LENGTH], int* all_words_cnt) {
    int i = 0;
    int max_word_length = 0; // 最长单词的长度
    int max_word_cnt = 0; // 最长单词数组的数目
    int word_cnt = 0;
    while (i < length) {
        char tmp_word[MAX_WORD_LENGTH]; // 临时存放单词
        int tmp_word_length = 0;

        // 将单词读入临时字符数组
        while (i < length && file[i] != ' '  && tmp_word_length < MAX_WORD_LENGTH) {
            tmp_word[tmp_word_length] = file[i];
            tmp_word_length++;
            i++;
        }
        tmp_word[tmp_word_length] = '\0';
        word_cnt++; // 顺便统计所有单词

        // 记录最长单词；
        if (max_word_cnt < MAX_WORD_NUM) { // 还能存下单词
            // 分几种情况：
            // 1. 这个单词长度比之前记录到的（所有）最长单词要长
            //    则写入最长单词，数组下标改为
            if (tmp_word_length > max_word_length) {
                max_word_cnt = 1;
                strcpy(max_len_words[max_word_cnt - 1], tmp_word);
                max_word_length = tmp_word_length;
            }
            // 2. 当前单词长度和之前的最长单词相等
            //    则继续写入单词
            else if (tmp_word_length == max_word_length) {
                max_word_cnt++;
                strcpy(max_len_words[max_word_cnt - 1], tmp_word);
            }
            // 3. 如果单词长度小于最长单词长度，则什么都不做
        }
        i++;
    }
    if (all_words_cnt != NULL) *all_words_cnt = word_cnt; // 如果指针不为空，则写入所有单词的数目
    return max_word_cnt;
}

// 找寻整数
int find_nums_in_(char file[], int length, int nums[MAX_INT_NUM]) {
    int i = 0;
    int int_cnt = 0;
    while (i < length)
    {
        char tmp_word[MAX_WORD_LENGTH]; // 临时存放单词
        int tmp_word_length = 0;

        // 读入连续的数字
        while (i < length && file[i] >= '0' && file[i] <= '9' && tmp_word_length < MAX_WORD_LENGTH) {
            tmp_word[tmp_word_length] = file[i];
            tmp_word_length++;
            i++;
        }
        tmp_word[tmp_word_length] = '\0';

        // 转换为int型后存储在数组中
        if (tmp_word_length > 0 && int_cnt < MAX_INT_NUM) {
            nums[int_cnt] = atoi(tmp_word);
            int_cnt++;
        }

        i++;
    }

    return int_cnt;
}

int main() 
{
    int letter_freq[128] = {0}; // 存储字幕出现的个数: 1-26 for a-z, 27-52 for A-Z
    char max_words[MAX_WORD_NUM][MAX_WORD_LENGTH] = {0}; // 最长的单词可能有多个
    int intgers_in_file[MAX_INT_NUM]; // 文件中出现的数字
    char file[MAX_FILE_LENGTH]; // 存放读取到的文件

    // 打开文件
    FILE* inputFile = fopen("file.txt", "r");
    int length = read_file_to_(file, inputFile);
    fclose(inputFile);

    // 统计字母频率
    for (int i = 0; i < length; ++i) add_letter_freq(file[i] ,letter_freq); 

    // 统计最长单词
    int all_words_cnt = 0;
    int max_words_cnt = find_max_len_word_in_(file, length, max_words, &all_words_cnt);

    // 统计出现的数字
    int numbers_cnt = find_nums_in_(file, length, intgers_in_file);

    // 输出结果：
    printf("Total %d words in file. \n", all_words_cnt);

    printf("Max words length is %d : \n", strlen(max_words[0]));
    for (int i = 0; i < max_words_cnt; ++i) {
        printf("    %s\n", max_words[i]);
    }
    printf("\n");

    printf("Letters statics: \n\n");
    for (int i = 1; i <= 26; i++) { // 小写字母统计输出
        printf("%c: %d\t", ('a'+i-1), letter_freq[i]);
        if (i % 7 == 0) printf("\n"); // 每7个字母一换行
    }
    printf("\n\n");
    for (int i = 1; i <= 26; i++) { // 大写字母统计输出
        printf("%c: %d\t", ('A'+i-1), letter_freq[26 + i]);
        if (i % 7 == 0) printf("\n"); // 每7个字母一换行
    }
    printf("\n");

    printf("Numbers in file: \n");
    for (int i = 1; i <= numbers_cnt; ++i) {
        printf("%d  ", intgers_in_file[i - 1]);
        if (i % 5 == 0) printf("\n"); // 每五个数字一换行
    }

    return 0;
}
